package org.kent.w.base.redis;

import lombok.Setter;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;

import java.util.concurrent.TimeUnit;

/**
 * Redis String 键值操作
 *
 * @author wu.jigang@geely.com
 * @version 1.0
 * @Date :Created by 2020/4/1.
 */
public class RedisStringOperator {

    @Setter
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 获取键值数据
     *
     * @param key
     * @return
     */
    public String get(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    /**
     * 设置键值并带有失效时间
     *
     * @param key
     * @param value
     * @param expireTime
     * @param timeUnit
     */
    public void set(String key, String value, long expireTime, TimeUnit timeUnit) {
        stringRedisTemplate.opsForValue().set(key, value, expireTime, timeUnit);
    }

    /**
     * 获取锁
     *
     * @param key
     * @param value
     * @param expireTime
     * @param timeUnit
     * @return
     */
    public Boolean tryLock(String key, String value, long expireTime, TimeUnit timeUnit) {

        final long expireSecond = timeUnit.toSeconds(expireTime);

        return stringRedisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException {

                RedisSerializer<String> serializer = stringRedisTemplate.getStringSerializer();
                byte[][] actualArgs = new byte[][] {
                        serializer.serialize(key),
                        serializer.serialize(value),
                        serializer.serialize("NX"),
                        serializer.serialize("EX"),
                        serializer.serialize(String.valueOf(expireSecond))
                };

                return redisConnection.execute("SET", actualArgs) != null;
            }
        });
    }

    /**
     * 解锁
     *
     * @param key
     * @param value
     * @return
     */
    public void unlock(String key, String value) {

        String v = get(key);

        // 需要对比value，防止误删，长时间未解锁时，key可能已经被其它线程重新设置
        if (v.equals(value)) {
            return ;
        }

        stringRedisTemplate.delete(key);
    }
}
